package com.wynne.ptldemo.actor;

import akka.actor.AbstractActor;
import akka.actor.Props;
import com.wynne.ptldemo.bo.TagSignalBo;
import com.wynne.ptldemo.consts.ResultBean;
import com.wynne.ptldemo.enums.RouteEvent;
import com.wynne.ptldemo.enums.RouteState;
import com.wynne.ptldemo.pojo.PtlAreaRoute;
import com.wynne.ptldemo.pojo.PtlRouteStatus;
import com.wynne.ptldemo.repository.PtlAreaRouteRepository;
import com.wynne.ptldemo.repository.PtlRouteStatusRepository;
import com.wynne.ptldemo.service.IActorService;
import com.wynne.ptldemo.statemachine.RouteActionStateMachine;
import com.wynne.ptldemo.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.squirrelframework.foundation.fsm.StateMachineBuilderFactory;
import org.squirrelframework.foundation.fsm.UntypedStateMachine;
import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;

import java.util.List;

@Slf4j
@Component
@Scope("prototype")
public class ControlActor extends AbstractActor implements IActorService {

    private ApplicationContext applicationContext;
    private UntypedStateMachineBuilder builder = null;
    private UntypedStateMachine fsm = null;

    public static Props createDefinedControlActor(ApplicationContext applicationContext) {
        return Props.create(ControlActor.class, applicationContext);
    }

    public ControlActor(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public ResultBean initActor(List<PtlRouteStatus> routeStatuses) {
        if (CollectionUtils.isEmpty(routeStatuses)) {
            return ResultBean.createByErrorMessage("流程为空");
        }
        builder = StateMachineBuilderFactory.create(RouteActionStateMachine.class);

        routeStatuses.forEach(d -> {
            builder.externalTransition().
                    from(d.getStatusCode()).
                    to(d.getNextStatus()).
                    on(d.getTriggerEvent()).
                    whenMvel(d.getTriggerWhere() == null ? "MyCondition:::1==1" : d.getTriggerWhere()).
                    callMethod(RouteEvent.TRIGGER.getCode());
            builder.onEntry(d.getNextStatus()).callMethod(RouteEvent.ENTRY.getCode());
            builder.onExit(d.getStatusCode()).callMethod(RouteEvent.EXIT.getCode());
        });

        fsm = builder.newStateMachine(RouteState.START.getCode());
        return ResultBean.createBySuccess(routeStatuses.get(0));
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder().matchAny(o -> {
            TagSignalBo tagSignalBo = (TagSignalBo) o;
            PtlAreaRouteRepository areaRouteRepository = (PtlAreaRouteRepository) SpringContextUtil.getBean("ptlAreaRouteRepository");
            PtlRouteStatusRepository routeStatusRepository = (PtlRouteStatusRepository) SpringContextUtil.getBean("ptlRouteStatusRepository");
            PtlAreaRoute areaRoute = areaRouteRepository.getByAreaNo(tagSignalBo.getAreaNo());
            List<PtlRouteStatus> routeStatuses = routeStatusRepository.findByRouteCodeOrderBySeq(areaRoute.getRouteCode());
            ResultBean resultInit = this.initActor(routeStatuses);
            if (!resultInit.isSuccess()) {
                return;
            }
            tagSignalBo.setRouteStatusList(routeStatuses);
            fsm.fire(((PtlRouteStatus) resultInit.getData()).getTriggerEvent(), tagSignalBo);
        }).build();
    }


}
